Hibernate2

持久化

将内存中的数据永久的存储到关系型数据库中

持久化类(元数据,映射)

一个Java类有了一个映射文件与数据库建立了关系,那么这个类就是持久化类

持久化类的编写规则

  1. 提供无参构造
  2. 类的属性需要私有,且提供共有的get和set方法
  3. 类的属性尽量使用包装类的类型
  4. 必须要有一个OID与表的主键对应
  5. 持久化类尽量不要使用final修饰

主键的分类

  1. 自然主键
    把具有业务含义的字段作为主键(例如将身份证号作为主键)
  2. 代理主键
    不具备业务含义的字段

主键生成策略

  1. 适用于代理主键
    increment:用于long,short或者int类型,有Hibernate自动以递增的方式生成唯一的标识符,每次增量为1
    identity:采用数据库本身提供的主键生成标识符,条件是数据库支持自动增长数据类型
    sequence:Hibernate根据底层数据库序列生成标识符,条件是数据库支持序列
    native:自动从identity、sequence、hlio中挑选一种使用
    uuid:采用128位的UUID算法来生成标识符
  2. 适用于自然主键
    assigned:由Java程序负责生成标识符,如果不指定id元素的generator
    属性,则默认使用该主键生成策略

持久化对象的三种状态

  1. 瞬时状态:不存在持久化标识OID,加入到了Session缓存中,且相关联的Session没有关闭,在数据库中有对应的记录。
  2. 持久状态:存在是持久化标识OID,加入到了Session缓存中,并且相关联的Session没有关闭,在数据库中有对应的记录。
  3. 脱管状态:存在持久化标识OID,并且仍然与数据库中的数据存在关联,只是失去了与当前session的关联。

持久化对象三种状态描述

  1. 当一个对象被执行 new 关键字后,该对象处于瞬时态;
  2. 当瞬时态对象执行Session的Save() 或 saveOrUpdate() 方法后,该对象被放入Session的一级缓存,对象进入持久态;
  3. 当持久态对象执行evict()、close()或clear()操作后,对象进入托管态;
  4. 当执行Session的get()、load()、find()或iterate()等方法从数据库查询对象时,查询到的对象也处于持久态;
  5. 当对数据库中的记录进行update()、saveOrUpdate()以及lock()等操作后,此时托管态的对象就过渡到持久态;
  6. 由于瞬时态和托管态的对象不在session的管理范围,所以会在一段时间后被JVM回收;

持久化对象三种状态的切换

  1. 瞬时态(由new关键字创建)转换到其他状态
    瞬时态转换为持久态:执行Session的save()或saveOrUpdate()方法
    瞬时态转换为托管态:为瞬时态对象设置持久化标识OID

    1
    2
    Customer customer = new Customer();  //瞬时态
    customer.setCust_id(1); //托管态
  2. 持久态(通过Session中的get()、load(),或者Query查询从数据库中获得)转换到其他状态
    持久态转换为瞬时态:执行Session的delete()方法
    持久态转换为托管态:执行Session的evict()、close()、clear()方法。evict()用于清除一级缓存中的某一个对象,close()方法用于关闭Session,clear()方法用于清除一级缓存的所有对象。

  3. 托管态(无法直接获得,由其他状态对象转换而来)转换到其他状态
    托管态转换为持久态:执行Session的update()、saveOrUpdate
    ()或lock()方法
    托管态转换为瞬时态:将托管态对象的持久化标识OID设置为null

持久态对象的特性

持久态对象能自动更新数据库

Hibernate一级缓存

Hibernate的缓存分为一级缓存和二级缓存,这两级缓存都位于持久化层。其中一层缓存为Hibernate内置缓存不能被卸载。一级缓存的作用就是减少对数据库的访问次数。
特点:
1)、当应用程序调用Session接口的save、update、saveOrUpdate方法时,如果Session缓存中没有相应的对象,Hibernate就会自动把从数据库查询到的相应对象信息加入到一级缓存中。
2)、当调用Session接口的load、get、以及Query接口的list、iterator方法时,会判断缓存中是否存在该对象,有则返回,不会查询数据库,如果没有,则取数据库中查询,并将其添加到一级缓存中。
3)、当调用Session的close方法时,Session将会被清空。

事务

事务的特性

  1. 原子性:(Atomic)要么全执行,要么全都不执行
  2. 一致性:(Consistency)事务完成时,所有的数据都保持一致
  3. 隔离性:(Isolation)一个事务不能被另一个事务干扰
  4. 持久性:(Durability)事务一旦提交,对数据库中的数据的改变就是永久性的

事务的并发问题

  1. 脏读:一个事务取到另一个事务未提交的数据
  2. 不可重复读:一个事务读到了另一个事务已经提交的update的数据,导致在同一个事务中的多次查询结果不一致
  3. 虚读/幻读:一个事务读到了另一个事务已经提交的insert的数据,导致在同一个事务中的多次查询结果不一致

事务的隔离级别

  1. 读未提交,一级
  2. 已提交读,二级
  3. 可重复读,四级
  4. 序列化/串行化,八级
    事务的隔离级别由数据库提供,并不是所有的数据库都支持四种隔离级别。在使用数据库的时候,隔离级别越高,高全性越高,性能越低。

Hibernate中的事务管理

在Hibernate中使用事务

1
2
3
Transaction tx = session.beginTransaction(); //开启事务
tx.commit(); //提交
tx.rollback(); //回滚

在Hibernate中设置事务的隔离级别

1
<property name="hibernate.connection.isolation">4</property>

Hibernate5中管理Session对象的三种方法

  1. Session对象的生命周期与本地线程绑定,thread
    1
    <property name="hibernate.current_session_content_class">thread</property>

Hibernate提供sessionFactory.getCurrentSession()创建一个session和ThreadLocal绑定

  1. Session对象的生命周期与JTA事务绑定,jta
  2. Hibernate委托程序管理Session对象的生命周期,managed

Query

HQL是Hibernate Query Language的缩写,语法很像SQL,但它完全面向对象。
使用步骤:

  1. 获得Hibernate的Session对象。
  2. 编写HQL
  3. 调用session.createQuery创建查询对象
  4. 如果HQL包含参数,则使用setXXX设置参数
  5. 调用Query对象的list()或uniqueResult()方法执行查询
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    简单示例

    package me.yanrs.service;
    import java.util.List;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import me.yanrs.domain.User;
    import me.yanrs.utils.HibernateUtils;
    public class HQL_Test {

    public static void main(String[] args) {
    hql_test();
    }

    public static void hql_test() {
    Session session = HibernateUtils.openSession();
    String hql = "from User where id=:id and name=:name";
    Query query = session.createQuery(hql);

    query.setInteger("id",1); //条件查询
    query.setString("name", "test");

    query.setFirstResult(0); //分页查询
    query.setMaxResults(5);

    List<User> list = query.list(); //list获取数据

    String hql2 = "from User";
    Query query2 = session.createQuery(hql2);

    System.out.println(query2.uniqueResult());
    System.out.println(list);
    }
    }

常用方法:setXXX、iterator、uniqueResult、executeUpdate、setFirstResult、setMaxResult

Criteria

又叫QBC(Query By Criteria)
使用步骤:

  1. 获得Hibernate的Session对象
  2. 通过Session获得Criteria对象
  3. 使用Restrictions的静态方法创建Criteria条件对象
  4. 使用Criteria对象中的add方法添加Criteria查询条件
  5. 执行Criteria的list()或者uniqueResult()获取结果
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    package me.yanrs.service;
    import java.util.List;

    import org.hibernate.Criteria;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.criterion.Restrictions;

    import me.yanrs.domain.User;
    import me.yanrs.utils.HibernateUtils;
    public class HQL_Test {

    public static void main(String[] args) {
    //hql_test();
    criteria_test();
    }

    public static void criteria_test() {
    Session session = HibernateUtils.openSession();
    Criteria createCriteria = session.createCriteria(User.class);

    System.out.println(createCriteria.list()); //查询全部

    createCriteria.add(Restrictions.eq("name", "test"));
    System.out.println(createCriteria.list()); //条件查询

    createCriteria.setFirstResult(0); //分页查询
    createCriteria.setMaxResults(5);
    System.out.println(createCriteria.list());

    System.out.println(createCriteria.uniqueResult());//获取查询的结果条数
    }
    }

SQLQuery

接收SQL语句进行查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
简单示例

package me.yanrs.service;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import me.yanrs.domain.User;
import me.yanrs.utils.HibernateUtils;
public class HQL_Test {

public static void main(String[] args) {
//hql_test();
//criteria_test();
sqlquery_test();
}

public static void sqlquery_test() {
//基本查询
String sql = "select * from user";
Session session = HibernateUtils.openSession();
SQLQuery query = session.createSQLQuery(sql);
System.out.println(query.list());

//封装到对象中
String sql1 = "select * from user";
Session session1 = HibernateUtils.openSession();
SQLQuery query1 = session.createSQLQuery(sql1);
query1.addEntity(User.class);
System.out.println(query1.list());

}
}